#ifndef _EXTREAM_MPMDCOMMM_HPP_
#define _EXTREAM_MPMDCOMMM_HPP_

#include "mpi.h"
// #include "types.hpp"
namespace EXTREAM {

const int INTER_COMM_TAG = 9;

/**
 * @brief
 *
 */
class MpmdComm {

public:
  static MpmdComm *getObjPtr() {
    if (instance == nullptr)
      instance = new MpmdComm;
    return instance;
  }

  /**
   * @brief 初始化
   *
   * @param peer_comm 包含两个组的通信子
   */
  void init(MPI_Comm peer_comm = MPI_COMM_WORLD);

  /**
   * @brief 初始化单个组,会对通信子进行拷贝
   *
   * @param comm
   */
  void initSPMD(MPI_Comm comm);

  ~MpmdComm();
  /**
   * @brief 在 mpi_finalize 函数之前调用此函数
   *
   */
  static void release();

  int remoteCommSize() const { return remote_comm_size_; }
  int localCommSize() const { return local_comm_size_; }
  MPI_Comm interComm() const { return inter_comm_; }
  int rankInLocal() const { return rank_in_local_; }
  MPI_Comm localComm() const { return local_comm_; }
  int appId() const { return app_id_; }

private:
  MPI_Comm peer_comm_{MPI_COMM_NULL};
  MPI_Comm local_comm_{MPI_COMM_NULL};
  MPI_Comm inter_comm_{MPI_COMM_NULL};
  int peer_comm_size_{0};
  int rank_in_peer_{-1}, rank_in_local_{-1};
  // remote_leader 是在 peer_comm 中的编号
  int local_leader_{0}, remote_leader_{0};
  int local_comm_size_{0}, remote_comm_size_{0};
  int app_id_{0};
  bool is_init_{false}, is_mpmd_{true};

  MpmdComm() {}

  static MpmdComm *instance;
};
} // namespace EXTREAM
#endif